/*

 * Copyright (c) 2014, Oracle America, Inc.

 * All rights reserved.

 *

 * Redistribution and use in source and binary forms, with or without

 * modification, are permitted provided that the following conditions are met:

 *

 *  * Redistributions of source code must retain the above copyright notice,

 *    this list of conditions and the following disclaimer.

 *

 *  * Redistributions in binary form must reproduce the above copyright

 *    notice, this list of conditions and the following disclaimer in the

 *    documentation and/or other materials provided with the distribution.

 *

 *  * Neither the name of Oracle nor the names of its contributors may be used

 *    to endorse or promote products derived from this software without

 *    specific prior written permission.

 *

 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE

 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF

 * THE POSSIBILITY OF SUCH DAMAGE.

 */

package org.openjdk.jmh.samples;


import org.openjdk.jmh.annotations.Benchmark;

import org.openjdk.jmh.annotations.BenchmarkMode;

import org.openjdk.jmh.annotations.CompilerControl;

import org.openjdk.jmh.annotations.Mode;

import org.openjdk.jmh.annotations.OutputTimeUnit;

import org.openjdk.jmh.annotations.Scope;

import org.openjdk.jmh.annotations.State;

import org.openjdk.jmh.runner.Runner;

import org.openjdk.jmh.runner.RunnerException;

import org.openjdk.jmh.runner.options.Options;

import org.openjdk.jmh.runner.options.OptionsBuilder;


import java.util.concurrent.TimeUnit;


@State(Scope.Thread)

@BenchmarkMode(Mode.AverageTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public class JMHSample_16_CompilerControl {


    /*

     * We can use HotSpot-specific functionality to tell the compiler what

     * do we want to do with particular methods. To demonstrate the effects,

     * we end up with 3 methods in this sample.

     */


    /**
     * These are our targets:
     * <p>
     * - first method is prohibited from inlining
     * <p>
     * - second method is forced to inline
     * <p>
     * - third method is prohibited from compiling
     * <p>
     * <p>
     * <p>
     * We might even place the annotations directly to the benchmarked
     * <p>
     * methods, but this expresses the intent more clearly.
     */


    public void target_blank() {

        // this method was intentionally left blank

    }


    @CompilerControl(CompilerControl.Mode.DONT_INLINE)

    public void target_dontInline() {

        // this method was intentionally left blank

    }


    @CompilerControl(CompilerControl.Mode.INLINE)

    public void target_inline() {

        // this method was intentionally left blank

    }


    @CompilerControl(CompilerControl.Mode.EXCLUDE)

    public void target_exclude() {

        // this method was intentionally left blank

    }


    /*

     * These method measures the calls performance.

     */


    @Benchmark

    public void baseline() {

        // this method was intentionally left blank

    }


    @Benchmark

    public void blank() {

        target_blank();

    }


    @Benchmark

    public void dontinline() {

        target_dontInline();

    }


    @Benchmark

    public void inline() {

        target_inline();

    }


    @Benchmark

    public void exclude() {

        target_exclude();

    }


    /*

     * ============================== HOW TO RUN THIS TEST: ====================================

     *

     * Note the performance of the baseline, blank, and inline methods are the same.

     * dontinline differs a bit, because we are making the proper call.

     * exclude is severely slower, becase we are not compiling it at all.

     *

     * You can run this test:

     *

     * a) Via the command line:

     *    $ mvn clean install

     *    $ java -jar target/benchmarks.jar JMHSample_16 -wi 0 -i 3 -f 1

     *    (we requested no warmup iterations, 3 iterations, single fork; there are also other options, see -h)

     *

     * b) Via the Java API:

     *    (see the JMH homepage for possible caveats when running from IDE:

     *      http://openjdk.java.net/projects/code-tools/jmh/)

     */


    public static void main(String[] args) throws RunnerException {

        Options opt = new OptionsBuilder()

                .include(JMHSample_16_CompilerControl.class.getSimpleName())

                .warmupIterations(0)

                .measurementIterations(3)

                .forks(1)

                .build();


        new Runner(opt).run();

    }
// 本例提到了JVM的方法内联，简单来说比较短但是执行频率又很高的方法，在执行多次后，JVM将该方法的调用替换为本身，以减少出栈入栈，从而减少性能的消耗。但是Java方法内联是无法人为控制的。

// JMH提供了可以控制是否使用内联的注解 @CompilerControl ，它的参数有如下可选：
//
// CompilerControl.Mode.DONT_INLINE：不使用内联CompilerControl.Mode.INLINE：强制使用内联CompilerControl.Mode.EXCLUDE：不编译
//
// Benchmark            Mode  Cnt   Score   Error  Units
// Sample16.baseline    avgt    3   0.261 ± 0.004  ns/op
// Sample16.blank       avgt    3   0.262 ± 0.005  ns/op
// Sample16.dontinline  avgt    3   1.711 ± 4.063  ns/op
// Sample16.exclude     avgt    3  52.937 ± 5.268  ns/op
// Sample16.inline      avgt    3   0.262 ± 0.027  ns/op
//
// 从执行结果可以看到内联方法和空方法执行速度一样，不编译执行最慢。

}

